<!--
 * @Description: 富文本编辑器
 * @Author: ZhangHan
 * @Date: 2025-06-20 10:02:01
 * @LastEditTime: 2025-08-11 18:27:26
 * @LastEditors: ZhangHan
-->
<template>
  <view class="editor_box">
    <!-- 操作栏 -->
    <view class="tooltar" v-if="showToolbar">
      <view v-for="(item, index) in ToolBarList" @tap="item.fnc()" :key="index">
        <image :src="item.icon" class="img" />
      </view>
    </view>
    <!-- uni这里 @input 首字母小写 -->
    <editor
      :id="`${id}`"
      :placeholder="'请输入内容'"
      @ready="editorReady"
      @input="handleEditorChange"
      style="color: black; padding: 12rpx"
      class="ql-container"
    />
  </view>
</template>

<script setup lang="ts">
import { ref, nextTick, getCurrentInstance } from "vue";
import { EDITORICON } from "@/concacts/imgPath";

interface EditorProps {
  showToolbar?: boolean;
  defaultContent?: string;
  id?: string;
}

type formatType = "bold" | "italic" | "header" | "align" | "list";
type formatVal = "h1" | "h2" | "h3" | "left" | "right" | "ordered" | "bullet";

const props = withDefaults(defineProps<EditorProps>(), {
  showToolbar: true,
});

const ToolBarList = [
  {
    fnc: () => insertImage(),
    icon: EDITORICON.ADDPIC,
  },
  {
    fnc: () => formatStyle("italic"),
    icon: EDITORICON.ITALIC,
  },
  {
    fnc: () => formatStyle("bold"),
    icon: EDITORICON.BOLD,
  },
  {
    fnc: () => formatStyle("header", "h1"),
    icon: EDITORICON.H1,
  },
  {
    fnc: () => formatStyle("header", "h2"),
    icon: EDITORICON.H2,
  },
  {
    fnc: () => formatStyle("header", "h3"),
    icon: EDITORICON.H3,
  },
  {
    fnc: () => formatStyle("align", "left"),
    icon: EDITORICON.LEFT,
  },
  {
    fnc: () => formatStyle("align", "right"),
    icon: EDITORICON.RIGHT,
  },
  {
    fnc: () => formatStyle("list", "ordered"),
    icon: EDITORICON.ORDERED,
  },
  {
    fnc: () => formatStyle("list", "bullet"),
    icon: EDITORICON.BULLET,
  },
  {
    fnc: () => undo(),
    icon: EDITORICON.UNDO,
  },
];

const emits = defineEmits(["editorChange"]);

const editorCtx = ref<any>(null); // 使用ref来存储editor上下文
const isEditorReady = ref(false);
const instance = getCurrentInstance() as any;

// // 编辑器实例化
const editorReady = () => {
  nextTick(() => {
    const query = uni.createSelectorQuery().in(instance?.proxy);
    query
      .select(`#${props?.id}`)
      .context((res: any) => {
        console.log("🚀 ~ editorReady ~ res:", res);
        if (res?.context) {
          editorCtx.value = res?.context;
          isEditorReady.value = true;
          if (props.defaultContent) {
            setEditorContent(props.defaultContent);
          }
        } else {
          console.error("获取编辑器上下文失败", res);
        }
      })
      .exec();
  });
};

// 设置编辑器内容
const setEditorContent = (html: string) => {
  return new Promise((resolve) => {
    if (!editorCtx.value) return resolve(false);

    editorCtx.value.setContents({
      html,
      success: () => {
        console.log("内容回显成功");
        resolve(true);
        // 初始化，向父组件赋值
        setTimeout(() => {
          handleEditorChange();
        }, 500);
      },
      fail: (err: any) => {
        console.error("内容回显失败:", err);
        resolve(false);
      },
    });
  });
};

//撤回上一步
const undo = () => {
  if (editorCtx.value) {
    editorCtx.value.undo();
  }
};

//样式转换
const formatStyle = (type: formatType, val?: formatVal) => {
  editorCtx.value.format(type, val);
};

//   插入图片
const insertImage = () => {
  uni.chooseImage({
    count: 1,
    sizeType: ["compressed"],
    sourceType: ["album", "camera"],
    success: (res) => {
      const filePath = res.tempFilePaths[0];

      // 方案1：直接使用本地路径（简单测试）
      if (editorCtx.value) {
        editorCtx.value.insertImage({
          src: filePath,
          width: "100%",
          success: () => {
            uni.showToast({ title: "插入成功", icon: "none" });
          },
        });
      }
    },
    fail: (err) => {
      console.log("选择图片失败", err);
    },
  });
};

// 编辑器内容变化处理
const handleEditorChange = (e?: any) => {
  console.log("🚀 ~ handleEditorChange ~ e:", e);
  // 获取编辑器内容
  getEditorContent().then((content) => {
    console.log("🚀 ~ getEditorContent ~ content:", content);
    // 向父组件传递内容
    emits("editorChange", content);
  });
};

// 获取编辑器内容
const getEditorContent = () => {
  return new Promise((resolve) => {
    if (editorCtx.value) {
      editorCtx.value.getContents({
        success: (res: any) => {
          console.log("🚀 ~ getEditorContent ~ res:", res);
          resolve({
            html: res?.html,
            text: res?.text,
          });
        },
      });
    }
  });
};
</script>

<style scoped lang="scss">
.editor_box {
  width: 100%;
  height: auto;
  box-sizing: border-box;
  background: #f7f7f7;
  border-radius: 12rpx;

  .ql-container {
    box-sizing: border-box;
    padding: 24rpx 32rpx;
    width: 100%;
    min-height: 30vh;
    max-height: 70vh;
    height: 100%;
    margin-top: 20rpx;
    overflow-y: scroll;
    line-height: 1.5;
  }
}

.tooltar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  box-sizing: border-box;
  padding: 10rpx 12rpx;
  border-bottom: 1rpx solid #ebebeb;
  view {
    .img {
      width: 24rpx;
      height: 24rpx;
    }
  }
}
</style>
